﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Spanner;

namespace SpannerWebSite
{
    class Program : UI
    {
        static HtmlID ChapterSectionID(SpannerChapter x, SpannerSection y)
        {
            return HtmlID(x.ID + "-" + y.ID);
        }

        static Html SectionHtml(SpannerChapter x, SpannerSection y)
        {
            return Group(
                H2(y.Title).WithID(ChapterSectionID(x, y)),
                y.Content
            );
        }

        static Html BannerHtml = Div().WithClass(CssClass.Banner).WithChildren(
            Div("Spanner").WithClass(CssClass.BannerMain),
            Div("Robust, single-page web app development.").WithClass(CssClass.BannerByline),
            Div("Last upated " + DateTime.Now.ToString("dd-MMM-yyyy")).WithClass(CssClass.BannerTimestamp)
        );

        internal static ObsVar<string> CurrChapterID = ObsVar<string>("currChapterID", "");

        internal static Var<Fn<string, string, Act>> NavigateToChapterSection =
            Procedure<string, string>("navigateToChapterSection", (chtr, secn) => Do(
                Set(CurrChapterID, chtr),
                JSAct("window.location.hash = # + '-' + #", chtr, secn),
                Local<DummyType>(
                    JSExpr<DummyType>("document.getElementById(#)", chtr + "-" + secn),
                    x => IfThen(x != null, JSAct("#.scrollIntoView()", x))
                )
            ));

        internal static Var<Fn<string, Act>> NavigateToChapter =
            Procedure<string>("navigateToChapter", (chtr) => Do(
                IfThen(chtr == "", Set(chtr, "Home")),
                Set(CurrChapterID, chtr),
                JSAct("window.location.hash = #", chtr),
                JSAct("window.scroll(0, 0)") // Scroll to the top of the page.
            ));

        static SpannerChapter[] Chapters = {
            Home.TheChapter,
            Intro.TheChapter,
            RefTopLevel.TheChapter,
            RefJS.TheChapter,
            RefKO.TheChapter,
            RefTypes.TheChapter,
            RefAlerts.TheChapter,
            RefArrays.TheChapter,
            RefDates.TheChapter,
            RefGlobals.TheChapter,
            RefMaths.TheChapter,
            RefRegExps.TheChapter,
            RefStrings.TheChapter
        };

        static Html TopLevelToCHtml()
        {
            return Div().WithClass(CssClass.TopLevelToC).WithChildren(
                    H3("Chapters"),
                    Group(
                        Chapters.Select(x =>
                            Div(A(x.Title)
                                    .WithAttr("href", "#" + x.ID.ToString())
                                    .KoClick(Call(NavigateToChapter, x.ID.ToString())))
                                .KoCss(CssClassCondition(CssClass.Selected, CurrChapterID == x.ID.ToString()))
                        )
                    )
                );
        }

        static Html ChapterToCHtml(SpannerChapter x)
        {
            return Div().WithClass(CssClass.ChapterToC).WithChildren(
                    H3(x.Title),
                    Group(
                        x.Sections.Select(y => Div(A(y.Title).WithAttr("href", "#" + ChapterSectionID(x, y))))
                    )
                );
        }

        static Html ChapterHtml(SpannerChapter x)
        {
            return Div()
                .KoVisible(CurrChapterID == x.ID.ToString())
                .WithChildren(
                    BannerHtml,
                    H1(x.Title),
                    ChapterToCHtml(x),
                    Group(x.Sections.Select(y => SectionHtml(x, y)))
                );
        }

        static void Main(string[] args)
        {
            // This sets CurrChapterID according to window.location.hash.
            var processWindowLocationHash = Procedure("processWindowLocationHash",
                Local(
                    Substr(JSExpr<string>("window.location.hash"), 1),
                    hash => 
                        IfThenElse(
                            IndexOf(hash, "-") == -1,
                            Call(NavigateToChapter, hash),
                            Call(NavigateToChapterSection,
                                Replace(hash, NewRegExp("-.*"), ""),
                                Replace(hash, NewRegExp(".*-"), "")
                            )
                        )
                )
            );

            var html = StandardSpannerHtmlPage("Spanner",
                Group(
                    // The next two magic lines prevent a loading "flash" while Knockout loads.
                    P("Loading...").KoVisible(false),
                    Div().WithAttr("style", "display: none").KoVisible(true).WithChildren(
                        //Link().WithAttr("href", "http://fonts.googleapis.com/css?family=Open+Sans")
                        //    .WithAttr("rel", "stylesheet")
                        //    .WithAttr("typeParliament Railway Station", "text/css"),
                        Style(SpannerWebSite.Properties.Resources.SpannerWebSiteCss),
                        Style(SpannerWebSite.Properties.Resources.SpannerWebSitePrismCss),
                        TopLevelToCHtml(),
                        Group(Chapters.Select(x => ChapterHtml(x)))
                    )
                )
            );

            var prism = new NonSpannerLibraryModel("prism", SpannerWebSite.Properties.Resources.SpannerWebSitePrismJS);

            var initAct = Do(
                Do(Chapters.SelectMany(x => x.InitActs)),
                JSAct("window.onhashchange = #", processWindowLocationHash),
                Call(processWindowLocationHash),
                Noop()
            );

            var webPage = WebPage("Spanner", html, initAct, new Model[] { prism });

            var ctxt = new Context(Const.WebSitePath);

            ctxt.WriteWebPage(webPage);
        }

    }
}
